package com.yunxin.core.application.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.common.utils.JacksonUtils;
import com.yunxin.core.application.assembler.ChannelAssembler;
import com.yunxin.core.application.dto.channel.ChannelPageInfoDTO;
import com.yunxin.core.application.dto.channel.ChannelPopupDTO;
import com.yunxin.core.application.dto.channel.ChannelPromotionCustomInfoDTO;
import com.yunxin.core.application.dto.channel.ChannelPromotionInfoDTO;
import com.yunxin.core.application.service.ChannelQueryGatewayService;
import com.yunxin.core.domain.external.channel.ChannelProhibitProductService;
import com.yunxin.core.domain.external.order.OrderExternalService;
import com.yunxin.core.domain.external.popup.PopupExternalService;
import com.yunxin.core.domain.external.product.ProductExternalService;
import com.yunxin.core.domain.external.product.ProductFromPopupDetail;
import com.yunxin.core.infra.common.channel.enums.PromotionStatusEnum;
import com.yunxin.core.infra.common.popup.PopupStatusEnum;
import com.yunxin.core.infra.persistence.entity.channel.ChannelProhibitProduct;
import com.yunxin.core.infra.persistence.entity.channel.ChannelPromotionCustomConfigDO;
import com.yunxin.core.infra.persistence.entity.channel.ChannelPromotionDO;
import com.yunxin.core.infra.persistence.entity.channel.query.result.ChannelPromotionDetailsResult;
import com.yunxin.core.infra.persistence.mapper.channel.ChannelPromotionCustomConfigExtendMapper;
import com.yunxin.core.infra.persistence.mapper.channel.ChannelPromotionExtendMapper;
import com.yunxin.core.utils.infra.common.constant.CommonConstants;
import com.yunxin.core.utils.infra.common.constant.CoreResultCode;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zero°
 * @since 2023-06-12
 */
@Service
@RequiredArgsConstructor
public class ChannelQueryGatewayServiceImpl implements ChannelQueryGatewayService {

    private final ChannelPromotionExtendMapper channelPromotionExtendMapper;

    private final ChannelPromotionCustomConfigExtendMapper channelPromotionCustomConfigExtendMapper;

    private final ChannelAssembler channelAssembler;

    private final PopupExternalService popupExternalService;

    private final ProductExternalService productExternalService;

    private final OrderExternalService orderExternalService;

    private final ChannelProhibitProductService channelProhibitProductService;


    @Override
    public ChannelPageInfoDTO getChannelPageInfoByPromotionCode(String channelPromotionCode) {
        String pageCode = channelPromotionExtendMapper.getChannelPageInfoByPromotionCode(channelPromotionCode);
        ChannelPageInfoDTO channelPageInfoDTO = new ChannelPageInfoDTO();
        channelPageInfoDTO.setPageCode(pageCode);
        return channelPageInfoDTO;
    }

    @Override
    public ChannelPromotionInfoDTO getChannelPromotionInfoByPromotionCode(String channelPromotionCode) {
        ChannelPromotionDetailsResult result = channelPromotionExtendMapper.getChannelPromotionDetailsResultByPromotionCode(channelPromotionCode);
       if (Objects.nonNull(result) && PromotionStatusEnum.DISABLE.getValue().equals(result.getPromotionStatus())){
            throw new BusinessException(CoreResultCode.CHANNEL_PROMOTION_STATUS_CLOSE);
        }
        ChannelPromotionInfoDTO infoDTO = channelAssembler.toChannelPromotionInfoDTO(result);
        infoDTO.setProtocolStatus(result.getProtocolStatus());
        return infoDTO;
    }

    @Override
    public ChannelPromotionCustomInfoDTO getChannelPromotionCustomInfoByPromotionCode(String channelPromotionCode) {
        ChannelPromotionCustomConfigDO channelPromotionCustomConfigDO =  channelPromotionCustomConfigExtendMapper.selectByChannelPromotionCode(channelPromotionCode);
        if(Objects.isNull(channelPromotionCustomConfigDO)) {
            return getDefaultChannelPromotionCustomInfoDTO();
        }
        String channelLogo = channelPromotionExtendMapper.selectChannelLogoByPromotionCode(channelPromotionCode);
        ChannelPromotionCustomInfoDTO channelPromotionCustomInfoDTO =  channelAssembler.toChannelPromotionCustomInfoDTO(channelPromotionCustomConfigDO);
        channelPromotionCustomInfoDTO.setChannelLogo(channelLogo);
        return channelPromotionCustomInfoDTO;
    }

    @Override
    public ChannelPopupDTO getChannelPopupInfoByPromotionCode(String channelPromotionCode, String userCode,List<Long> UvList) {
        ChannelPromotionDO channelPromotionDO = channelPromotionExtendMapper.selectByPromotionCode(channelPromotionCode);
        if(Objects.nonNull(channelPromotionDO)){
            String lastPopupProductData = popupExternalService.getLastPopupProductData(channelPromotionDO.getPopupCode(), PopupStatusEnum.PUBLISHED.getValue());
            if(CharSequenceUtil.isEmpty(lastPopupProductData)){
                return null;
            }
            List<Long> productIds = JacksonUtils.X.parse(lastPopupProductData, new TypeReference<>() {});
            if(CollUtil.isEmpty(productIds)){
                return null;
            }
            // 去掉没有撞库成功的
            if(CollUtil.isNotEmpty(UvList)){
                for (Long id : UvList) {
                    for (int i = 0; i < productIds.size(); i++) {
                        if(Objects.equals(productIds.get(i), id)){
                            productIds.remove(id);
                            i--;
                        }
                    }
                }
            }

            List<ChannelProhibitProduct> channelProhibitProduct = channelProhibitProductService.getChannelProhibitProduct(channelPromotionDO.getChannelId());
            List<Long> prohibitProductIds = new ArrayList<>();
            if (CollUtil.isNotEmpty(channelProhibitProduct)) {
                prohibitProductIds = channelProhibitProduct.stream().map(ChannelProhibitProduct::getProductId).toList();
            }

            List<Long> existOrderProductId = orderExternalService.listUvOrderProductIdByUser(userCode);
            List<ProductFromPopupDetail> productFromPopupDetails = productExternalService.listProductDetailsByIds(productIds);
            List<Long> finalProhibitProductIds = prohibitProductIds;
            Map<Long, ProductFromPopupDetail> map = productFromPopupDetails.stream()
                    .filter(x->!existOrderProductId.contains(x.getProductId()))
                    .filter(x->!finalProhibitProductIds.contains(x.getProductId()))
                    .collect(Collectors.toMap(ProductFromPopupDetail::getProductId, Function.identity()));
            List<Long> list = productFromPopupDetails.stream().map(ProductFromPopupDetail::getProductId).toList();
            for (Long productId : list) {
                ProductFromPopupDetail productFromPopupDetail = map.get(productId);
                if(Objects.nonNull(productFromPopupDetail) && Boolean.TRUE.equals(productFromPopupDetail.getValid())){
                    ChannelPopupDTO channelPopupDTO = new ChannelPopupDTO();
                    channelPopupDTO.setProductId(productFromPopupDetail.getProductId());
                    channelPopupDTO.setProductName(productFromPopupDetail.getProductName());
                    channelPopupDTO.setProductImage(productFromPopupDetail.getProductImage());
                    channelPopupDTO.setProductSolGan(productFromPopupDetail.getProductSolGan());
                    channelPopupDTO.setProductLabeling(Optional.ofNullable(productFromPopupDetail.getProductLabeling()).filter(StringUtils::isNotBlank).map(l -> Arrays.asList(l.split(CommonConstants.COMMA))).orElse(Collections.emptyList()));
                    channelPopupDTO.setJumpUrl(productFromPopupDetail.getJumpUrl());
                    channelPopupDTO.setUserProtocol(productFromPopupDetail.getUserProtocol());
                    channelPopupDTO.setUserProtocolList(JacksonUtils.X.parse(productFromPopupDetail.getUserProtocol(), new TypeReference<>() {}));
                    return channelPopupDTO;
                }
            }
        }
        return null;
    }

    /**
     * 获取默认 ChannelPromotionCustomInfoDTO
     * @return ChannelPromotionCustomInfoDTO
     */
    @NotNull
    private ChannelPromotionCustomInfoDTO getDefaultChannelPromotionCustomInfoDTO() {
        ChannelPromotionCustomInfoDTO dto = new ChannelPromotionCustomInfoDTO();
        dto.setIdentityNoStatus(1);
        dto.setSesameSeedStatus(1);
        dto.setCreditCardStatus(1);
        dto.setEducationLevelStatus(1);
        dto.setHouseStatus(1);
        dto.setVehicleStatus(1);
        dto.setAccumulationFundStatus(1);
        dto.setSocialSecurityStatus(1);
        dto.setInsureStatus(1);
        dto.setCareerStatus(1);
        dto.setMonthlyIncomeStatus(1);
        return dto;
    }
}
